﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using gts;
using BCommon;

namespace GTS
{
    class GTS800
    {
        private static readonly object SynLocktcp = new object();

        public const int GTS800_FIRST_AXIS_NUM = 1;					// 起始轴号
        public const double GTS800_ST = 200.0;					// 控制周期 us
        public const double GTS800_ST_PMS = 1000.0/GTS800_ST;		// 1ms占多少控制周期

        public const int GTS800_BUSY = 1 << 10;			// 轴运行标志			
        public const int GTS800_SERVO = 1 << 9;	// 伺服使能标志
        public const int GTS800_CAPT = 1 << 3;		// 捕获标志
        public const int GTS800_LIMIT_P = 1 << 5;	// 正限位标志
        public const int GTS800_LIMIT_N = 1 << 6;		// 负限位标志

        public const int GTS800_TOTAL_AXIS_NUM = (3);					// 轴的总数

        public const int ERR_GTS800_CONTROL_NO_RESPONSE = (-7);	// 运动控制器无响应
        public const int ERR_GTS800_OPEN_FAILED = (-6);	// 运动控制卡打开失败
        public const int ERR_GTS800_COMMUNICATION = (-1);	// 主机和运动控制器通讯错误
        public const int ERR_GTS800_NO_ERROR = (0);	// 无错误
        public const int ERR_GTS800_COMMAND = (1);	// 指令错误
        public const int ERR_GTS800_LICENSE_ERROR = (2);	// license不支持
        public const int ERR_GTS800_PARAMETERS_CONFLICT = (7);	// 指令参数错误

        public const uint TOTAL_CARD_NUM = (1);	// 总卡数
        public short m_iIndex=0;
        short m_nCardNum;		// 当前卡号
        int []m_nAxisNum=new int[GTS800_TOTAL_AXIS_NUM];// 当前出错的轴号
        uint []m_nAxisSts=new uint[GTS800_TOTAL_AXIS_NUM];// 出错的时候状态
        bool []m_bServoMode=new bool[GTS800_TOTAL_AXIS_NUM];
        string []DestCfgFile=new string[GTS800_TOTAL_AXIS_NUM];//.CFG配置文件路径
        int m_nError;							// 错误代码
        private bool m_IniSts = false;          //复位标志
        int m_nOptValue;						// 输出端口状态
        int m_nIptValue;						// 输入端口状态
        double[] m_pdfScale;						// 脉冲当量
        double[] m_pdfGRT;						// 脉冲当量
        public void IGTS800()
        {
	        uint i = 0;
	        m_IniSts =false;
	        for(i = 0; i < GTS800_TOTAL_AXIS_NUM; i++)
	        {
		        m_nAxisNum[i] = 0;
		        m_nAxisSts[i] = 0x0000;	
		        m_bServoMode[i] = false;
	        }
        }
        public void ErrorHandle()
        {
	        if (!m_IniSts)return;

	        string str;
	        switch(m_nError)
	        {
	        case ERR_GTS800_CONTROL_NO_RESPONSE:
		        str = "运动控制器无响应";
		        break;
	        case ERR_GTS800_OPEN_FAILED:
		        str = "运动控制卡打开失败";
		        break;
	        case ERR_GTS800_COMMUNICATION: 
		        str = "主机和运动控制器通讯错误";
		        break;
	        case ERR_GTS800_NO_ERROR: 
		        //str = "半径参数错误";
		        return;
	        case ERR_GTS800_LICENSE_ERROR: 
		        str = "license不支持";
		        break;
	        case ERR_GTS800_COMMAND: 
		        str = "指令错误";
		        break;
	        case ERR_GTS800_PARAMETERS_CONFLICT: 
		        str = "指令参数错误";
		        break;
	        default:
		        str = "未定义错误";
		        break;
	        }

        }

       public short H_GetFirstAxisNum()
        {
	        return GTS800_FIRST_AXIS_NUM;	
        }

        public short H_GetTotalAxisNum()
        {
	        return GTS800_TOTAL_AXIS_NUM;	
        }

        public bool IsServoAxis(uint nAxis)
        {
	        return m_bServoMode[nAxis - GTS800_FIRST_AXIS_NUM];
        }
        public void ServoMode(uint nAxis,bool bServo)
        {
	        m_bServoMode[nAxis - GTS800_FIRST_AXIS_NUM] = bServo;
        }

        public bool H_Init()
        {
            IGTS800();
	        short i = 0;	
	        string str;
	        m_nCardNum = m_iIndex++;

	        //切换当前运动控制卡号
	        //m_nError = GT_SetCardNo(m_nCardNum);			ErrorHandle();

	        //打开卡
            try
            {
                m_nError = mc.GT_Open(0, 1);
            }
            catch(Exception ex)
            { }
            ErrorHandle();

	        if(ERR_GTS800_NO_ERROR != m_nError)
	        {
	            MessageBox.Show("打开第0张固高运动控制卡失败！");
		        return false;
	        }	
	        //复位运动控制器
	        //m_nError = GT_Reset();					ErrorHandle();

	        if(ERR_GTS800_NO_ERROR != m_nError)
	        {
		        return false;
	        }

            DestCfgFile[0] = Bini.GetExePath() + "GTS800.cfg";
          

	        m_nError = mc.GT_LoadConfig(DestCfgFile[0]);	ErrorHandle();

            m_nError = mc.GT_ClrSts(1, 8); ErrorHandle();

            m_nError = mc.GT_HomeInit();					// 初始化自动回原点功能            
	        // 设置轴脉冲 + 方向,使能
            for (i = GetFirstAxisNum(); i < GetFirstAxisNum() + GetTotalAxisNum(); i++)
	        {
		        //m_nError = GT_StepDir(i);					ErrorHandle();
                m_nError = mc.GT_AxisOn(i); ErrorHandle();
	        }
	        Thread.Sleep(100);


	        m_IniSts =true;

	        return true;

        }

        public bool H_UnInit()
        {
	        if (!m_IniSts)return false;
	        int i;
            for (i = GetFirstAxisNum(); i < GetFirstAxisNum() + GetTotalAxisNum(); i++)
	        {
                Stop((short)i, true);		
	        }

            for (i = GetFirstAxisNum(); i < GetFirstAxisNum() + GetTotalAxisNum(); i++)
	        {
		        //GT_SwitchtoCardNo(m_nCardNum);				ErrorHandle();
		        //GT_Axis(i);									ErrorHandle();
		        mc.GT_AxisOff((short)i);									ErrorHandle();
	           

	        }
            SetOutput(0x0000);

	        m_iIndex--;
	        if(0 == m_iIndex)
	        {
                mc.GT_Close();
	        }
            m_IniSts = false;
	        return true;
        }

        public bool H_IsMove(short nAxis)
        {
	        if (!m_IniSts)return false;
	        uint nSts = (uint)H_GetStatus(nAxis);
            int nIndex = nAxis - H_GetFirstAxisNum();
	        if(0 == m_nAxisNum[nIndex] )
	        {
		        if(0x0200 != ( nSts & 0x02F2))
		        {
			        m_nAxisNum[nIndex] = 1;
			        m_nAxisSts[nIndex] = ( nSts & 0x02F2);
		        }
		        else
		        {
			        m_nAxisSts[nIndex] = 0x0000;
		        }
	        }
	        if(0 != ( nSts & GTS800_BUSY))
	        {
		        return true;
	        }
	        return false;
        }
        public bool ReachLimit()
        {
	        if (!m_IniSts)return false;
	        int i = 0;
	        int nValue = 0;
            for (i = 0; i < GTS800_TOTAL_AXIS_NUM; i++)
	        {
		        nValue += m_nAxisNum[i];
	        }
	        if(0 == nValue)
	        {
		        return false;
	        }
	        else
	        {
		        return true;
	        }

        }
        public bool AxisError(uint nAxis,out uint nSts)
        {
            if (!m_IniSts)
            {
                nSts = 0;
                return false;
                
            }
	        if(0 == m_nAxisNum[nAxis - H_GetFirstAxisNum()])
	        {
		        nSts = 0x0000;
		        return false;
	        }
	        else
	        {
		        nSts = m_nAxisSts[nAxis - H_GetFirstAxisNum()];
		        return true;
	        }

        }

        public bool H_IsServoOn(short nAxis)
        {
	        if (!m_IniSts)return false;
	        if(0 != (H_GetStatus(nAxis) & GTS800_SERVO))
	        {
		        return true;
	        }
	        return false;
        }

        public int H_GetInput()
        {
	        if (!m_IniSts)return 0;
	        int nSts = 0;

	        //参数MC_GPI表示通用输入IO口
            m_nError = mc.GT_GetDi(mc.MC_GPI, out nSts); ErrorHandle();
            return (~nSts);
        }
        public int H_GetOutput()
        {
	        if (!m_IniSts)return 0;
	        int nSts = 0;

	        //参数MC_GPI表示通用输入IO口
            m_nError = mc.GT_GetDo(mc.MC_GPO, out nSts); ErrorHandle();
	        return (~nSts);
        }
        public double H_GetCmdPos(short nAxis)
        {
	        if (!m_IniSts)return 0;

	        double lValue = 0;
            uint pClock = 0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_GetPrfPos(nAxis, out lValue,1,out pClock); ErrorHandle();

	        return lValue;
        }

        public double H_GetEncPos(short nAxis)
        {
	        if (!m_IniSts)return 0;
	        double lValue = 0.0;
            uint pClock = 0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_GetEncPos(nAxis, out lValue, 1, out pClock); ErrorHandle();
	        return lValue;
        }

        public bool H_GetCaptPos(short nAxis,out int lPos)
        {
            if (!m_IniSts)
            {
                lPos = 0;
                return false;
            }
            uint pClock = 0;    
	        short nStatus = 0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_GetCaptureStatus(nAxis, out nStatus, out lPos, 1,out pClock); ErrorHandle();
	        if(1 == nStatus)
	        {		
		        return true;
	        }
	        return false;
        }

        public void H_SetOutput(int nValue)
        {
	        if (!m_IniSts)return ;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_SetDo(mc.MC_GPO, (~nValue)); ErrorHandle();
        }

        public int H_GetStatus(short nAxis)
        {
	        if (!m_IniSts)return 0;
	        int nValue = 0;
            uint pClock = 0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_GetSts(nAxis, out nValue, 1,out pClock); ErrorHandle();

	        return nValue;
        }

        public bool H_SetVel(short nAxis,double dfVel)
        {
	        if (!m_IniSts)return false;
	        double dfValue = 0.0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
	        dfValue = InRange(dfVel/GTS800_ST_PMS,1.0,16384.0);
            m_nError = mc.GT_SetVel(nAxis, dfValue); ErrorHandle();
	        return true;
        }
        public bool H_SetAcc(short nAxis,double dfAcc)
        {
	        if (!m_IniSts)return false;
	        double dfValue = 0.0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();

	        dfValue = InRange(dfAcc/(GTS800_ST_PMS * GTS800_ST_PMS),0.0,16384.0);
	        //m_nError = GT_SetAcc(nAxis,dfValue);				ErrorHandle();
	        return true;
        }

        public bool H_Move(short nAxis, int lPos, double dfVel, double dfAcc)
        {
            if (!m_IniSts) return false;
            m_nAxisNum[nAxis - H_GetFirstAxisNum()] = 0;
            double dfValue = 0.0;
            mc.TTrapPrm trap;
            //m_nError = GT_SetCardNo(m_nCardNum);					ErrorHandle();

            m_nError = mc.GT_ClrSts(nAxis, 1); ErrorHandle();
            // 位置清零
            //GT_ZeroPos(nAxis);										ErrorHandle();
            //轴规零划位置清

            //m_nError = GT_SetPrfPos(nAxis,0);							ErrorHandle();

            //轴设置为点位模式
            m_nError = mc.GT_PrfTrap(nAxis); ErrorHandle();
            
            dfValue = InRange(dfAcc / (GTS800_ST_PMS * GTS800_ST_PMS), 0.0, 16384.0);

            trap.velStart = 0;
            trap.acc = dfAcc;
            trap.dec = dfAcc;
            trap.smoothTime = 50;
            //设置点动运行参数
            m_nError = mc.GT_SetTrapPrm(nAxis, ref trap); ErrorHandle();

            dfValue = InRange(dfVel / GTS800_ST_PMS, 1.0, 16384.0);
            m_nError = mc.GT_SetVel(nAxis, dfVel); ErrorHandle();
            m_nError = mc.GT_SetPos(nAxis, lPos); ErrorHandle();
            //m_nError = GT_SetPos(nAxis,-50000L);						ErrorHandle();
            //m_nError = GT_SetVel(nAxis,50)	;					ErrorHandle();

            m_nError = mc.GT_Update(1 << (nAxis - 1)); ErrorHandle();


            return true;
        }
        public bool H_Home(short nAxis, int lPos, double dfVel, double dfAcc)
        {
            if (!m_IniSts) return false;
            mc.GT_HomeStop(nAxis, lPos, dfVel, dfAcc);// 轴2为Home回零模式
            return true;
        }

        public bool H_CaptMove(short nAxis, int lPos, double dfVel, double dfAcc)
        {
            if (!m_IniSts) return false;
            m_nAxisNum[nAxis - H_GetFirstAxisNum()] = 0;
            double dfValue = 0.0;
            mc.TTrapPrm trap;
            //m_nError = GT_SetCardNo(m_nCardNum)	;					ErrorHandle();
            m_nError = mc.GT_ClrSts(nAxis, 1); ErrorHandle();
            m_nError = mc.GT_SetCaptureMode(nAxis, mc.CAPTURE_INDEX); ErrorHandle();

            m_nError = mc.GT_SetPrfPos(nAxis, 0); ErrorHandle();

            //轴设置为点位模式
            m_nError = mc.GT_PrfTrap(nAxis); ErrorHandle();

            dfValue = InRange(dfAcc / (GTS800_ST_PMS * GTS800_ST_PMS), 0.0, 16384.0);

            trap.velStart = 0;
            trap.acc = 0.2;
            trap.dec = 0.125;
            trap.smoothTime = 30;
            //设置点动运行参数
            m_nError = mc.GT_SetTrapPrm(nAxis, ref trap); ErrorHandle();

            dfValue = InRange(dfVel / GTS800_ST_PMS, 1.0, 16384.0);
            m_nError = mc.GT_SetVel(nAxis, 50); ErrorHandle();
            m_nError = mc.GT_SetPos(nAxis, lPos); ErrorHandle();
            //m_nError = GT_SetPos(nAxis,-50000L);						ErrorHandle();
            //m_nError = GT_SetVel(nAxis,50)	;					ErrorHandle();

            m_nError = mc.GT_Update(1 << (nAxis - 1)); ErrorHandle();

            return true;
        }
        public bool H_CaptMoveHome(short nAxis, int lPos, double dfVel, double dfAcc)
        {
            if (!m_IniSts) return false;
            m_nAxisNum[nAxis - H_GetFirstAxisNum()] = 0;
            double dfValue = 0.0;
            mc.TTrapPrm trap;
            //m_nError = GT_SetCardNo(m_nCardNum)	;					ErrorHandle();
            m_nError = mc.GT_ClrSts(nAxis, 1); ErrorHandle();
            m_nError = mc.GT_SetCaptureMode(nAxis, mc.CAPTURE_HOME); ErrorHandle();

            m_nError = mc.GT_SetPrfPos(nAxis, 0); ErrorHandle();

            //轴设置为点位模式
            m_nError = mc.GT_PrfTrap(nAxis); ErrorHandle();

            dfValue = InRange(dfAcc / (GTS800_ST_PMS * GTS800_ST_PMS), 0.0, 16384.0);

            trap.velStart = 0;
            trap.acc = 0.2;
            trap.dec = 0.125;
            trap.smoothTime = 30;
            //设置点动运行参数
            m_nError = mc.GT_SetTrapPrm(nAxis, ref trap); ErrorHandle();

            dfValue = InRange(dfVel / GTS800_ST_PMS, 1.0, 16384.0);
            m_nError = mc.GT_SetVel(nAxis, dfVel); ErrorHandle();
            m_nError = mc.GT_SetPos(nAxis, lPos); ErrorHandle();
            //m_nError = GT_SetPos(nAxis,-50000L);						ErrorHandle();
            //m_nError = GT_SetVel(nAxis,50)	;					ErrorHandle();

            m_nError = mc.GT_Update(1 << (nAxis - 1)); ErrorHandle();

            return true;
        }

        public bool H_Move(short nAxis, int lPos)
        {
	        if (!m_IniSts)return false;
	        m_nAxisNum[nAxis - H_GetFirstAxisNum()] = 0;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_ClrSts(nAxis,1); ErrorHandle();
            m_nError = mc.GT_SetPos(nAxis, lPos); ErrorHandle();
            m_nError = mc.GT_Update(nAxis); ErrorHandle();


	        return true;
        }

        public bool H_Stop(int nAxis,bool bSmooth)
        {
	        if (!m_IniSts)return false;

            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();

	        if(!bSmooth)
	        {
                m_nError = mc.GT_Stop(1 << (nAxis - 1), 1 << (nAxis - 1)); ErrorHandle();
	        }
	        else
	        {
                m_nError = mc.GT_Stop(1 << (nAxis - 1), ~(1 << (nAxis - 1))); ErrorHandle();
	        }
	        return true;
        }

       public bool H_ZeroPos(short nAxis)
        {
	        if (!m_IniSts)return false;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();
            m_nError = mc.GT_ClrSts(nAxis,1); ErrorHandle();
            m_nError = mc.GT_ZeroPos(nAxis,1); ErrorHandle();
	        return true;
        }

        public bool H_ServoEn(short nAxis, bool bOn)
        {
	        if (!m_IniSts)return false;
            m_nError = mc.GT_SetCardNo(m_nCardNum); ErrorHandle();

	        if(bOn)
	        {
                m_nError = mc.GT_AxisOn(nAxis); ErrorHandle();
	        }
	        else
	        {
                m_nError = mc.GT_AxisOff(nAxis); ErrorHandle();
	        }
	        return true;	
        }
        public bool H_HomeByLimit(short AxisNo, int nDir, double dfVel, double dfAcc)
        {
	        if (!m_IniSts)return false;
	        double []dfPos=new double[2] ;
	        string str;		
	        // 快速撞限位
            Stop(AxisNo, true);
            Move(AxisNo, -700 * nDir, dfVel * 10, dfAcc);	
	        WaitStop(AxisNo,0);
	        Thread.Sleep(500);
           
	        ZeroPos(AxisNo);
            Move(AxisNo, 5 * nDir, dfVel, dfAcc);
            WaitStop(AxisNo, 0);
            Thread.Sleep(500);
            Move(AxisNo, -200 * nDir, dfVel, dfAcc);
            WaitStop(AxisNo, 0);
            Thread.Sleep(500);
            ZeroPos(AxisNo);
            if (AxisNo != 3)
            { 
                Move(AxisNo, 5 * nDir, dfVel, dfAcc); 
            }
            else
            {
                Move(AxisNo, nDir, dfVel, dfAcc);
            }
            WaitStop(AxisNo, 0);
            Thread.Sleep(500);
            ZeroPos(AxisNo);

	        return true;
        }
        public bool H_HomeByHome(short AxisNo, int nDir, double dfVel, double dfAcc)
        {
            if (!m_IniSts) return false;
            double[] dfPos = new double[2];

            // 快速撞限位
            //Move(AxisNo, -365 * nDir, dfVel * 2, dfAcc);
            //WaitStop(AxisNo, 0);
            //Thread.Sleep(500);
            //ZeroPos(AxisNo);
            //Move(AxisNo, 10 * nDir, dfVel, dfAcc);
            //WaitStop(AxisNo, 0);
            //Thread.Sleep(500);
            //Move(AxisNo, -365 * nDir, dfVel, dfAcc);
            //WaitStop(AxisNo, 0);
            //Thread.Sleep(500);
            Stop(AxisNo, true);
            ZeroPos(AxisNo);
            // X1慢速离开
            CaptMoveHome(AxisNo, 365 * nDir, dfVel, dfAcc);
            WaitStop(AxisNo, 0);
            Thread.Sleep(500);
            if (!GetCaptPos(AxisNo, out dfPos[0]))
            {
                MessageBox.Show("复位失败");
            }
            Move(AxisNo, dfPos[0], dfVel, dfAcc);
            WaitStop(AxisNo, 0);
            Thread.Sleep(500);
            ZeroPos(AxisNo);

            return true;
        }

        public bool H_HomeByIndex(short AxisNo, int nDir,double dfVel, double dfAcc)
        {
	        if (!m_IniSts)return false;
            double[] dfPos = new double[2];
	    		
	        // 快速撞限位
            Move(AxisNo, -10000 * nDir, dfVel * 2, dfAcc);	
	        WaitStop(AxisNo,0);	
	        Thread.Sleep(500);
            ZeroPos(AxisNo);
            Move(AxisNo, 10 * nDir, dfVel, dfAcc);	
	        WaitStop(AxisNo,0);	
	        Thread.Sleep(500);
            Move(AxisNo, -10000 * nDir, dfVel, dfAcc);	
	        WaitStop(AxisNo,0);	
	        Thread.Sleep(500);
            ZeroPos(AxisNo);
	        // X1慢速离开
	        CaptMove(AxisNo,10*nDir,dfVel,dfAcc);
	        WaitStop(AxisNo,0);
	        Thread.Sleep(500);
	        if(!GetCaptPos(AxisNo,out dfPos[0]))
	        {
		        MessageBox.Show("复位失败");
	        }
            Move(AxisNo, dfPos[0], dfVel, dfAcc);
	        WaitStop(AxisNo,0);
	        Thread.Sleep(500);
            ZeroPos(AxisNo);

	        return true;
        }

        public bool WaitStop(short nAxis,uint nCard=0)
        {
	        if (!m_IniSts)return true;
	        if(nCard >= TOTAL_CARD_NUM)
	        {
		        MessageBox.Show("大于总卡数量，返回！");
		        return false;
	        }
	        while(IsMove(nAxis))	
	        {
		       Thread.Sleep(1);
	        }
	        return true;
        }

        public bool H_SetHSIO(short nAxis, int lPos)
        {
	        // 设置当1轴编码器位置为1000时HSIO0输出脉冲
            int lPos2 = 0;
            mc.GT_CompareData(nAxis, // 对1轴进行位置比较输出
		        1, // 需要进行比较的数据源为外部编码器
		        0, // 到达比较位置后输出高低电平  0脉冲
		        0, // 初始状态
		        500, // 脉冲宽度为 500us,0无效
		        ref lPos, // HSIO0 的比较位置缓冲区数据起始地址
		        1, // HSIO0 的比较位置缓冲区数据长度
                ref lPos2,
		        0);
	        // 设置 HSIO0 输出时，同时锁存 1、 2 轴编码器
	        //	m_nError = GT_SetCaptureMode(1, CAPTURE_HSIO0);
	        m_nError = mc.GT_SetCaptureMode(nAxis, mc.CAPTURE_HSIO0);
	        // 当编码器到达 1000 脉冲时锁存 1、 2 轴编码器，
	        //	m_nError = GT_GetCaptureStatus(nAxis, &pSts, &pVal);
	        // 	m_nError = GT_GetCaptureStatus(2, &pSts, &pVal);
	        return true;
        }
        public bool H_SetHSIO2(short nAxis, int[] lPos, short nNum)
        {
	        // 设置当1轴编码器位置为1000时HSIO0输出脉冲
            int []pBuf1=new int[20];
	        for (int i=0;i<nNum;i++)
	        {
		        pBuf1[i]=lPos[i];
	        }
            mc.GT_CompareData(nAxis, // 对1轴进行位置比较输出
		        1, // 需要进行比较的数据源为外部编码器
		        0, // 到达比较位置后输出高低电平  0脉冲
		        0, // 初始状态
		        500, // 脉冲宽度为 500us,0无效
		        ref pBuf1[0], // HSIO0 的比较位置缓冲区数据起始地址
		        nNum, // HSIO0 的比较位置缓冲区数据长度
                 ref pBuf1[2],
		        0);
	        // 设置 HSIO0 输出时，同时锁存 1、 2 轴编码器
	        //	m_nError = GT_SetCaptureMode(1, CAPTURE_HSIO0);
            m_nError = mc.GT_SetCaptureMode(nAxis, mc.CAPTURE_HSIO0);
	        // 当编码器到达 1000 脉冲时锁存 1、 2 轴编码器，
	        //	m_nError = GT_GetCaptureStatus(nAxis, &pSts, &pVal);
	        // 	m_nError = GT_GetCaptureStatus(2, &pSts, &pVal);
	        return true;
        }
        public double InRange(double dfValue,double dfMin, double dfMax)
        {
	        if(dfValue < dfMin)
	        {
		        dfValue = dfMin;
	        }
	        else if(dfValue > dfMax)
	        {
		        dfValue = dfMax;
	        }
	        return dfValue;
        }
        public double GetCmdPos(short nAxis)
        {
	        double dfValue = 0.0;
	        if((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                dfValue = H_GetCmdPos(nAxis);
	            }
	            if(null != m_pdfScale)
		        {
			        dfValue /= m_pdfScale[nAxis - GetFirstAxisNum()];
		        }
	
	        }
	        else
	        {
		        dfValue = 9999999999.9999999;
	        }
	        return dfValue;
        }
        public double GetEncPos(short nAxis)
        {
	        double dfValue = 0.0;
	        if((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                dfValue = H_GetEncPos(nAxis)*m_pdfGRT[nAxis - GetFirstAxisNum()];
	            }
                if (null != m_pdfScale)
		        {
			        dfValue /= m_pdfScale[nAxis - GetFirstAxisNum()];
		        }
		
	        }
	        else
	        {
                dfValue = 9999999999.9999999;
	        }
	        return dfValue;
        }

        /// <summary>
        /// 得到轴的规划位置或编码器位置
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="Cmd">true 规划位置，false 编码器位置</param>
        /// <returns></returns>
        public double GetMotoPos(short nAxis,bool Cmd)
        {
            if (Cmd) return GetCmdPos(nAxis);//读取规划位置，原型函数“GT_GetPrfPos”；

	        return GetEncPos(nAxis);//读取编码器位置
        }
        public bool GetCaptPos(short nAxis,out double dfPos)
        {
	        bool bFlag = false;
	        int lValue = 0;
            dfPos = 9999999999.9999999;
	        if((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                bFlag = H_GetCaptPos(nAxis,out lValue);
	            }
                if (null != m_pdfScale)
		        {
			        dfPos = lValue /m_pdfScale[nAxis - GetFirstAxisNum()];
		        }
		
	        }
	        return bFlag;
        }
        public bool SetOutput(int nBit, bool bOn)
        {
	        m_nOptValue=H_GetOutput();
            lock (SynLocktcp)
            {
                if (!m_IniSts) return false;
	            if(bOn)
	            {
		            m_nOptValue |= (1 << nBit);	
	            }
	            else
	            {
		            m_nOptValue &= ~((1 << nBit));	
	            }
                 H_SetOutput(m_nOptValue);              
            }
            return true;
        }



        public void SetOutput(int nValue)
        {
	        if(m_IniSts)
	        {
		        lock (SynLocktcp)
                {
		            H_SetOutput(nValue);
		            m_nOptValue = nValue;    
                }
	        }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AxisNo"></param>
        /// <param name="nDir">负限位为1，正限为-1</param>
        /// <param name="dfVel"></param>
        /// <param name="dfAcc"></param>
        /// <returns></returns>
        public bool HomeByLimit(short AxisNo, int nDir, double dfVel, double dfAcc)
        {
	        bool nValue = false;
            if (m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_HomeByLimit(AxisNo, nDir, dfVel, dfAcc);
	            }
	        }
	        return nValue;
        }
        public bool HomeByHome(short AxisNo, int nDir, double dfVel, double dfAcc)
        {
            bool nValue = false;
            if (m_IniSts)
            {
                lock (SynLocktcp)
                {
                    nValue = H_HomeByHome(AxisNo, nDir, dfVel, dfAcc);
                }
            }
            return nValue;
        }

        public bool HomeByIndex(short AxisNo, int nDir, double dfVel, double dfAcc)
        {
	        bool nValue = false;
            if (m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_HomeByIndex(AxisNo, nDir, dfVel, dfAcc);
	            }
	        }
	        return nValue;
        }
        public int GetInput()
        {
	        int nValue = 0;
            if (m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_GetInput();
	            }
	        }
	        return nValue;
        }
        public int GetOutput()
        {
	        int nValue = 0;
            if (m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_GetOutput();
	            }
	        }
	        return nValue;
        }
        public int GetStatus(short nAxis)
        {
	        int nValue = 0;
            if ((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_GetStatus(nAxis);
	            }
	        }
	        return nValue;
        }

        public bool ServoEn(short nAxis,bool bEnable)
        {
            if ((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
		        return false;
	        }
            lock (SynLocktcp)
            {
                H_ServoEn(nAxis, bEnable);
            }
            return true;
        }
        public bool Init()
        {	
	        bool bFlag = false;	
	
	            lock (SynLocktcp)
	            {
	                bFlag = false;

                    if (!m_IniSts)
	                {

	                    m_nError = 0;
	                    m_IniSts = false;
                        m_pdfScale = null;

                        if (null == m_pdfScale)
	                    {
	                        m_pdfScale = new double[GetTotalAxisNum()];
	                    }
                        if (null == m_pdfGRT)
	                    {
	                        m_pdfGRT = new double[GetTotalAxisNum()];
	                    }
	                    int i = 0;
	                    for (i = 0; i < GetTotalAxisNum(); i++)
	                    {
	                        m_pdfScale[i] = 1.0;
	                    }
	                    for (i = 0; i < GetTotalAxisNum(); i++)
	                    {
	                        m_pdfGRT[i] = 1.0;
	                    }

	                    bFlag = H_Init();

	                    m_IniSts = bFlag;
	                    m_nOptValue = GetOutput();
	                }

	            }
	        ZeroPos(1);

	        return bFlag;
        }
        public bool UnInit()
        {
	        bool bFlag = false;
            if (!m_IniSts) 
	        {
		        return false;
	        }
            lock (SynLocktcp)
            {
                bFlag = H_UnInit();
                if (bFlag)
                {
                    m_IniSts = !bFlag;
                }
            }
            return true;
        }
        public short GetFirstAxisNum()
        {
	        return H_GetFirstAxisNum();	
        }
        public short GetTotalAxisNum()
        {
	        return H_GetTotalAxisNum();	
        }
        public bool IsMove(short nAxis)
        {
            if (!m_IniSts) 
	        {
		        return false;
	        }
	        bool bFlag = true;
            lock (SynLocktcp)
            {
                bFlag = H_IsMove(nAxis);
            }
            return bFlag;
        }
        public bool IsServoOn(short nAxis)
        {
            if (!m_IniSts) 
	        {
		        return false;
	        }

	        bool bFlag = true;
            lock (SynLocktcp)
            {
                bFlag = H_IsServoOn(nAxis);
            }
            return bFlag;
        }
        /// <summary>
        /// 使轴停止，bSmooth:是否平滑停止
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="bSmooth">是否平滑停止</param>
        /// <returns></returns>
        public bool Stop(short nAxis, bool bSmooth)
        {
	        bool bFlag = false;

	        if((m_IniSts) && (IsAxisNumValid(nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                bFlag = H_Stop(nAxis, bSmooth);
	            }
	        }

	        return bFlag;
        }

        public int UnitToPulse(double dfValue)
        {
	        int lValue = 0;
	        double dfFlag = 1.0;
	        if(dfValue < 0.0)
	        {
		        dfFlag = -1.0;
	        }

	        dfValue *= dfFlag;
	        lValue = (int)(dfValue + 0.5);
            lValue *= (int)dfFlag;
	        return lValue;
        }
        public bool Move(int nAxis, double dfPos,double dfVel,double dfAcc)
        {
	        bool bFlag = false;
	        int i = 0;
        
	        if((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
                    i = nAxis - GetFirstAxisNum();
                    bFlag = H_Move((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos),
                            dfVel*m_pdfScale[i]/ 1000.0 /* mm/s */, 
                            dfAcc *m_pdfScale[i]/ 1000.0 /* mm/s.s */);
	            }
	        }

	        return bFlag;
        }
        public bool Home(int nAxis, double dfPos, double dfVel, double dfAcc)
        {
            bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
            {
                lock (SynLocktcp)
                {
                    i = nAxis - GetFirstAxisNum();
                    bFlag = H_Move((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos),
                    dfVel * m_pdfScale[i] / 1000.0, // mm/s
                    dfAcc * m_pdfScale[i] / 1000.0); // mm/s.s
                }
            }

            return bFlag;
        }
        public bool SetVel(int nAxis, double dfVel)
        {
	        bool bFlag = false;
	        int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
                    bFlag = H_SetVel((short)nAxis, dfVel * m_pdfScale[i] / 1000.0); // pulse/ms
	            }
	        }

	        return bFlag;
        }
        public bool SetAcc(int nAxis, double dfAcc)
        {
	        bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
                    bFlag = H_SetAcc((short)nAxis, dfAcc * m_pdfScale[i] / 1000.0); // mm/ms.ms
	            }
	        }

	        return bFlag;
        }
        public bool Move(int nAxis, double dfPos)
        {
	        bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
                    bFlag = H_Move((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos));
	            }
	        }

	        return bFlag;
        }
        public bool SetHSIO(int nAxis, double dfPos)
        {
	        bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
                    bFlag = H_SetHSIO((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos));
	            }
	        }

	        return bFlag;
        }
        public bool SetHSIO2(int nAxis, out double[] dfPos, short nNum)
        {
	        bool bFlag = false;
            int i = 0;
            dfPos = new double[nNum];
            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
	                int[]nPos = new int[nNum];

	                for (int j = 0; j < nNum; j++)
	                {
	                    nPos[j] = UnitToPulse(m_pdfScale[i]*dfPos[j]);
	                }
                    bFlag = H_SetHSIO2((short)nAxis, nPos, nNum);
	               
	            }
	        }
            else
            {        
                dfPos[0] = 0;
            }
	        return bFlag;
        }
        public bool CaptMove(int nAxis, double dfPos, double dfVel, double dfAcc)
        {
	        bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
	        {
	            lock (SynLocktcp)
	            {
	                i = nAxis - GetFirstAxisNum();
                    bFlag = H_CaptMove((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos),
	                    dfVel*m_pdfScale[i]/1000.0, // mm/ms
	                    dfAcc*m_pdfScale[i]/1000.0); // mm/ms.ms
	            }
	        }

	        return bFlag;
        }
        public bool CaptMoveHome(int nAxis, double dfPos, double dfVel, double dfAcc)
        {
            bool bFlag = false;
            int i = 0;

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
            {
                lock (SynLocktcp)
                {
                    i = nAxis - GetFirstAxisNum();
                    bFlag = H_CaptMoveHome((short)nAxis, UnitToPulse(m_pdfScale[i] * dfPos),
                        dfVel * m_pdfScale[i] / 1000.0, // mm/ms
                        dfAcc * m_pdfScale[i] / 1000.0); // mm/ms.ms
                }
            }

            return bFlag;
        }

        public bool GetInput(short nBit)
        {
	        int nValue = 0;
	        if(m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_GetInput();
	                nValue &= (1 << nBit);
	            }
	        }
	        if(nValue != 0)
	        {
		        return true;
	        }
	        return false;
        }
        public bool GetOutput(short nBit)
        {
            int nValue = 0;

	        if(m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                nValue = H_GetOutput();
	                nValue &= (1 << nBit);
	            }
	        }
	        if(nValue != 0)
	        {
		        return true;
	        }
	        return false;
        }
        /// <summary>
        /// 设置脉冲当量
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="dfScale"></param>
        /// <returns></returns>
        public bool SetScale(short nAxis, double dfScale)
        {
	        if(!IsAxisNumValid(nAxis))
	        {
		        return false;
	        }
	        if(dfScale > 0.0)
	        {
                if (null != m_pdfScale)
		        {
			        m_pdfScale[nAxis - GetFirstAxisNum()] = dfScale;
			        return true;
		        }
	        }
	        return false;

        }
        public bool SetGRT(short nAxis, double dfScale)
        {
	        if(!IsAxisNumValid(nAxis))
	        {
		        return false;
	        }
            if (null != m_pdfGRT)
	        {
		        m_pdfGRT[nAxis - GetFirstAxisNum()] = dfScale;
		        return true;
	        }
	        return false;

        }

        /// <summary>
        /// 轴号是否存在
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <returns></returns>
        public bool IsAxisNumValid(short nAxis)
        {
	        if((nAxis >= GetFirstAxisNum()) && (nAxis < GetFirstAxisNum() + GetTotalAxisNum()))
	        {
		        return true;
	        }
	        return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="nAxis"></param>
        /// <returns></returns>
        public bool ZeroPos(short nAxis)
        {
	        bool bFlag = false;

	        if(m_IniSts)
	        {
	            lock (SynLocktcp)
	            {
	                bFlag = H_ZeroPos(nAxis);
	            }
	        }

	        return bFlag;
        }

        public void H_LimitOff(short nAxis, short LimitType)
        {

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
            {
                lock (SynLocktcp)
                {
                    mc.GT_LmtsOff(nAxis, LimitType);
                }
            }


        }

        public void H_LimitOn(short nAxis, short LimitType)
        {

            if ((m_IniSts) && (IsAxisNumValid((short)nAxis)))
            {
                lock (SynLocktcp)
                {
                    mc.GT_LmtsOn(nAxis, LimitType);
                }
            }


        }
    }
}
